<?php
class Documents extends Controller {
	
	public function __construct()
  {
    parent::Controller();
  }

  public function index() {
    
    // check if the request is a document search
    if (!empty($_REQUEST['query'])) {
      return $this->searchDocuments($_REQUEST);
    }
    
  	// collect request parameters
		$start  = isset($_REQUEST['start'])  ? $_REQUEST['start']  :  0;
		$count  = isset($_REQUEST['limit'])  ? $_REQUEST['limit']  : 20;
		$sort   = isset($_REQUEST['sort'])   ? $_REQUEST['sort']   : '';
		$dir    = isset($_REQUEST['dir'])    ? $_REQUEST['dir']    : 'ASC';
		$filters = isset($_REQUEST['filter']) ? $_REQUEST['filter'] : null;	
		
  	// GridFilters sends filters as an Array if not json encoded
		if (is_array($filters)) {
		    $encoded = false;
		} else {
		    $encoded = true;
		    $filters = json_decode($filters);
		}
		
		// initialize variables
		$where = ' 0 = 0 ';
		$qs = '';
		
		// loop through filters sent by client
		if (is_array($filters)) {
		    for ($i=0;$i<count($filters);$i++){
		        $filter = $filters[$i];
		
		        // assign filter data (location depends if encoded or not)
		        if ($encoded) {
		            $field = $filter->field;
		            $value = $filter->value;
		            $compare = isset($filter->comparison) ? $filter->comparison : null;
		            $filterType = $filter->type;
		        } else {
		            $field = $filter['field'];
		            $value = $filter['data']['value'];
		            $compare = isset($filter['data']['comparison']) ? $filter['data']['comparison'] : null;
		            $filterType = $filter['data']['type'];
		        }
		
		        switch($filterType){
		            case 'string' : $qs .= " AND ".$field." LIKE '%".$value."%'"; Break;
		            case 'list' :
		                if (strstr($value,','))  {
		                    $fi = explode(',',$value);
		                    for ($q = 0; $q < count($fi); $q++){
		                        $fi[$q] = "'".$fi[$q]."'";
		                    }
		                    $value = implode(',',$fi);
		                    $qs .= " AND ".$field." IN (".$value.")";
		                } else {
		                    $qs .= " AND ".$field." = '".$value."'";
		                }
		            Break;
		            case 'boolean' : $qs .= " AND ".$field." = ".($value); Break;
		            case 'numeric' :
		                switch ($compare) {
		                    case 'eq' : $qs .= " AND ".$field." = ".$value; Break;
		                    case 'lt' : $qs .= " AND ".$field." < ".$value; Break;
		                    case 'gt' : $qs .= " AND ".$field." > ".$value; Break;
		                }
		            Break;
		            case 'date' :
		                switch ($compare) {
		                    case 'eq' : $qs .= " AND ".$field." = '".date('Y-m-d',strtotime($value))."'"; Break;
		                    case 'lt' : $qs .= " AND ".$field." < '".date('Y-m-d',strtotime($value))."'"; Break;
		                    case 'gt' : $qs .= " AND ".$field." > '".date('Y-m-d',strtotime($value))."'"; Break;
		                }
		            Break;
		        }
		    }
		    $where .= $qs;
		}

		//->where('u.name LIKE ?', "%$name%")
		
		/*
		 * De momento no existe filtrado
		 */
				
		$q = Doctrine_Query::create()
			->select('d.*')
			->from('Document d')
			->where($where);
			
  	if ($sort != "") {
		    //$query .= " ORDER BY ".$sort." ".$dir;
		    $q->orderBy($sort.' '.$dir);
		}
		
		$q->offset($start);
		$q->limit($count);
			
		$results = $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
		//print_r($results);
		
		//$total = mysql_query("SELECT COUNT(id) FROM demo WHERE ".$where);
		$q = Doctrine_Query::create()
			->select('COUNT(*) AS total')
			->from('Document')
			->where($where);
		
		$result = $q->fetchArray();
		$total = $result[0]['total'];

		// return response to client
		echo json_encode(array('success' => true, 'message' => 'Datos cargardo exitosamente', 'documents' => $total, 'data' => $results));
  }
  
	/**
	 * Funcion create del conjunto CRUD. Crea uno o varios records segund peticion del cliente
	 * Los records son enviado en codificacion JSON.
	 * 
	 * @return JSON object
	 */
  public function create() {
  	$sucessResult = true;
  	$document = null;
  	$result = null;
  	
  	if( isset($_REQUEST['data']) ) {
  		$data = json_decode($_REQUEST['data']);
  		
  		if( $data ) {
	  		if( is_array($data) ) {
	  			$documents = array();
	  			foreach( $data as $document_post ) {
	  				// create document using
	  				if( ($d = $this->createDocument($document_post)) ) {
	  					$documents[] = $d->toFlatArray();	
	  				}
	  				else {
	  					$sucessResult = false;
	  					break;
	  				}
	  			}
	  			
	  			$result = $documents; 
	  		}
	  		else { // simple documento
	  			$document = $this->createDocument($data);
	  			$sucessResult = $document ? true : false;	
	  		}
  		}
  		else {
  			$message = 'JSON decode error: '.jsonGetLastError();
  			$sucessResult = false;	
  		}
  	}
  	else { // error parametros title y authors no fueron suministrados
  		$message = 'El t&iacute;tulo y el nombre del autor son dos par&aacute;metros requerido para crear un documento';
  		$sucessResult = false;
  	}
  	
  	if( $sucessResult ) {
  		if( is_array($data) ) {
  			$message = 'Documentos creados exitosamente.';	
  		}	
  		else {
  			$result = $document->toFlatArray();
  			$message = 'Documento creado exitosamente';
  		}
  	}
  	else if( $data ) {
  		$message = is_array($data) ? 'Error al crear los documentos.' : 'Error al crear el documento.';	
  	}
  	
  	echo json_encode(array('success' => $sucessResult, 'message' => $message, 'data' => $result));
		//echo '{"success":'.json_encode($sucessResult).', "message":"'.$message.'", "data":'.json_encode($result).'}';
  }
  
  /**
   * 
   * @return JSON object
   */
  public function delete() {
  	$data = isset($_REQUEST['data'])  ? json_decode($_REQUEST['data']) : 0;
  	$success = false;
  	$message = '';
  	
  	// TODO Adicionar alguna logica para eliminar el archivo relacionado del sitema de archivo. Los archivos estan en la tabla File
  	
  	if( !$data) {
  		$message = 'Error al eliminar record. Id(s) no proporcionado(s).';
  	}	else {
  		if( !is_array($data) ) {
  			$filename = File::getFilenameByDocument_Id((int)$data);
  			// La llamada a esta funcion aqui es algo temporal, pues la idea es poder usar el controlador de archivo
  			// pero para reutilizar controladores dentro de otro controlador en codeigniter se necesita de HMVC extension 
  			// y es un reguero que hay que organizar y por una sola funcion por el momento no adicionare HMVC al proyecto.
  			$result = $this->remove($filename);
  			if ($result != '{"success":true}') {
  			  echo $result;
  			  return;  
  			}
  		  
  			$q = Doctrine_Query::create()
		    		->delete('Document')
		    		->addWhere('id = ?', (int)$data);
		    		
		    $deleted = $q->execute();
		    
				if( !$deleted ) {
					$success = false;
  				$message = 'El record con Id = '.$data.' no pudo ser eliminado.';
				}	else {
					$success = true;
  				$message = 'Record eliminado exitosamente.';	
				}
  		}
  		else {
	  		foreach($data as $document_id) {
  	  		$filename = File::getFilenameByDocument_Id((int)$document_id);
    			// La llamada a esta funcion aqui es algo temporal, pues la idea es poder usar el controlador de archivo
    			// pero para reutilizar controladores dentro de otro controlador en codeigniter se necesita de HMVC extension 
    			// y es un reguero que hay que organizar y por una sola funcion por el momento no adicionare HMVC al proyecto.
    			$result = $this->remove($filename);
    			if ($result != '{"success":true}') {
    			  echo $result;
    			  return;  
    			}
	  		  
	  			$q = Doctrine_Query::create()
		    		->delete('Document')
		    		->addWhere('id = ?', (int)$document_id);
		
		    	$deleted = $q->execute();
		    	
					if( !$deleted ) {
						$success = false;
	  				$message = 'El record con Id = '.$data.' no pudo ser eliminado.';
	  				echo json_encode(array('success' => $success, 'message' => $message));
	  				return;
					}
	  		}
	  		$success = true;
	  		$message = 'Records eliminados exitosamente.';
  		}
  	}
  	
  	echo json_encode(array('success' => $success, 'message' => $message));
  	//echo '{"success":'.json_encode($success).', "message":"'.$message.'"}';//,"documents":"0","data":'.json_encode($results).'}';
  }
  
  /**
   * 
   * @return nothing
   */
  public function update() {
  	$data = isset($_REQUEST['data'])  ? json_decode($_REQUEST['data'], true) : 0;
  	  	
  	$sucessResult = true;
  	$document = null;
  	$message = '';
  	$result = '';

  	if( !$data ) {
  		$sucessResult = false;
  		$message = !isset($_REQUEST['data']) ? 'El parametro data no fue enviado en el pedido del cliente y este es necesario.' : 'JSON decode error: '.jsonGetLastError();
  	}
  	else {
  		$document = new Document();
  		$document->assignIdentifier($data['id']);		// assign an Identifier to change from insert to update mode.
  		$document->refresh();												// refresh the record.
  		$document->refreshRelated();								// refresh the relationships.
  		
  		if( isset($data['documentType']) ) {			
  			$document->changeDocumentType($data['documentType']);
  		}
  		
  		$document->updateValues($data);
  		$document->documentTypeMapper()->updateValues($data);
  		$document->save();
  		
  		$result = $document->toFlatArray();
  		$message = 'Documento actualizado exitosamente.';
  	}
  	
  	echo json_encode(array('success' => $sucessResult, 'message' => $message, 'data' => $result));
  	//echo '{"success":'.json_encode($sucessResult).', "message":"'.$message.'", "data":'.json_encode($result).'}';
  }
  
  /**
   * 
   * @return nothing
   */
  public function getDocumentTypes() {
  	$q = Doctrine_Query::create()
			->select('*')
			->from('DocumentType');
			
		$result = $q->fetchArray();
		
		echo json_encode(array('rows' => $result));
  }
 
  /**
   * 
   * @param unknown_type $documentData
   * @return unknown_type
   */
  private function createDocument($documentData) {
  	$document = new Document();
		$document->title = $documentData->title;
		$document->authors = $documentData->authors;
		$document->createdBy = Current_User::user()->uid;
		$document->updatedBy = Current_User::user()->uid;	
		
		if (is_array($documentData->files) && !empty($documentData->files)) {
		  foreach ($documentData->files as $file_name) {
  			$file = new File();
  		  $file->name = $file_name;
  		  $document->files[] = $file;  
		  }
		}
		
		// if there is not documentType, the default one is added
		if ( !isset($documentData->documentType) ) {
			$document->documentType = DOCUMENTTYPE_THESIS;
			$document->thesis = new Thesis();
			$document->thesis->tutors = 'Especifique el nombre de los tutores.';
		} 
		else {
			$document->documentType = $documentData->documentType;
			$document->createDetailsByDocumentType();
			
			// patch until other solution is found to this
			$data = array();
			foreach ($documentData as $key => $value) {
				$data[$key] = $value;
			}
			// end if patch
			
			$document->updateValues($data);
  		$document->documentTypeMapper()->updateValues($data);
		}
		
		try {
			$document->save();
		} catch (Doctrine_Exception $e) {
			throw $e;
		}
		
		return $document;
  }
  
  // method to handle DocumentDetail
  public function getDocumentDetailed() {
  	if( isset($_REQUEST['parameters'] ) ) {
  		$parameters = json_decode($_REQUEST['parameters']);	
  		
  		if( $parameters == NULL || !is_int($parameters->id) || !is_int($parameters->documentType) ) {
  			$message = $parameters == NULL ? 'JSON decode error: '.jsonGetLastError() : 'Alguno de los parametros es incorrecto.';
  			echo json_encode(array('success' => false, 'message' => $message));
  			return false;
  		}
  		
  		$document = new Document();
  		$document->id = $parameters->id;
  		$document->documentType = $parameters->documentType;
  		$result = $document->findByDocumentTypeWithDetails();
  		if( $result ) {
  		  echo json_encode(array('success' => true, 'message' => 'Detalles del documento cargados exitosamente.', 'data' => $result));
  		  return true;
  		}
  		else {
  		  echo json_encode(array('success' => false, 'message' => 'No hubo resultados relacionados con el record Id = '.$parameters->id.'.'));	
  		}
  	}		
  	else {
  	  echo json_encode(array('success' => false, 'message' => 'Objeto parameters no esta definido en el pedido y este es necesario.'));	
  	}
  	return false;
  }
  
  /**
   * 
   * @param unknown_type $filename
   * @return string|string|string
   */
  private function remove($filename) {
    $target_path = UPLOADS_PATH.$filename;
    if (!is_file($target_path)) {
      return json_encode(array('success' => false, 'errors' => array('title' => 'Error', 'errormsg' => 'El archivo '.$filename.' no existe. Contacte al administrador y pregunte por este problema.')));
    }

    if (unlink($target_path)) {
      return json_encode(array('success' => true));
    }
    
    return json_encode(array('success' => false, 'errors' => array('title' => 'Error al remover', 'errormsg' => 'El archivo '.$filename.' no pudo ser eliminado. Contacte al administrador y pregunte por este problema.')));
  }
  
  private function searchDocuments($request) {
    // collect request parameters
		$start  = isset($request['start'])  ? $request['start']  :  0;
		$count  = isset($request['limit'])  ? $request['limit']  : 20;
		$sort   = isset($request['sort'])   ? $request['sort']   : '';
		$dir    = isset($request['dir'])    ? $request['dir']    : 'ASC';
		$filters = isset($request['filter']) ? $request['filter'] : null;	
		
		$value = $request['query'];
		$value = '%'.$value.'%';
		
		// initialize variables
		$where = ' 0 = 0 ';
		$qs = '';
		
		$q = Doctrine_Query::create()
				->select('d.*')
				->from('Document d')
				->leftJoin('d.catalogs c')
				->leftJoin('d.thesis t')
				->leftJoin('d.masterThesis mt')
				->leftJoin('d.phdThesis pt')
			  ->leftJoin('d.book b')
			  ->leftJoin('d.encyclopedia e')
			  ->leftJoin('d.magazineArticle m')
				->where('d.title LIKE ?', $value)
				->orWhere('d.authors LIKE ?', $value)
				->orWhere('d.abstract LIKE ?', $value)
				->orWhere('d.keywords LIKE ?', $value)
				->orWhere('d.tags LIKE ?', $value)
				// catalogs
				->orWhere('c.identification LIKE ?', $value)
				// thesis
			  ->orWhere('t.tutors LIKE ?', $value)
			  ->orWhere('t.department LIKE ?', $value)
			  ->orWhere('t.faculty LIKE ?', $value)
			  ->orWhere('t.knowledgeArea LIKE ?', $value)
			  // masterThesis
			  ->orWhere('mt.tutors LIKE ?', $value)
			  ->orWhere('mt.department LIKE ?', $value)
			  ->orWhere('mt.faculty LIKE ?', $value)
			  ->orWhere('mt.knowledgeArea LIKE ?', $value)
			  // phdThesis
			  ->orWhere('pt.tutors LIKE ?', $value)
			  ->orWhere('pt.department LIKE ?', $value)
			  ->orWhere('pt.faculty LIKE ?', $value)
			  ->orWhere('pt.knowledgeArea LIKE ?', $value)
			  // book
			  ->orWhere('b.city LIKE ?', $value)
			  ->orWhere('b.edition LIKE ?', $value)
			  ->orWhere('b.editors LIKE ?', $value)
			  ->orWhere('b.publisher LIKE ?', $value)
			  ->orWhere('b.knowledgeArea LIKE ?', $value)
			  // encyclopedia
			  ->orWhere('e.edition LIKE ?', $value)
			  ->orWhere('e.publisher LIKE ?', $value)
			  ->orWhere('e.publisher LIKE ?', $value)
			  // magazineArticle
			  ->orWhere('m.city LIKE ?', $value);
			  
  	if ($sort != "") {
		    $q->orderBy($sort.' '.$dir);
		}
		
		$q->offset($start);
		$q->limit($count);
		
//		try { 
		  $results = $q->execute(array(), Doctrine_Core::HYDRATE_ARRAY);
//		} catch (Doctrine_Exception $e) {
//		  echo json_encode(array('success' => false, 'message' => 'Code: '.$e->getPortableCode().'<br/>Message : '.$e->getPortableMessage()));
//		  return;
//		}
    
		if ($sort != "") {
		    //$query .= " ORDER BY ".$sort." ".$dir;
		    $q->orderBy($sort.' '.$dir);
		}

		$q = Doctrine_Query::create()
				->select('COUNT(*) AS total')
				->from('Document d')
				->leftJoin('d.catalogs c')
				->leftJoin('d.thesis t')
				->leftJoin('d.masterThesis mt')
				->leftJoin('d.phdThesis pt')
			  ->leftJoin('d.book b')
			  ->leftJoin('d.encyclopedia e')
			  ->leftJoin('d.magazineArticle m')
				->where('d.title LIKE ?', $value)
				->orWhere('d.authors LIKE ?', $value)
				->orWhere('d.abstract LIKE ?', $value)
				->orWhere('d.keywords LIKE ?', $value)
				->orWhere('d.tags LIKE ?', $value)
				// catalogs
				->orWhere('c.identification LIKE ?', $value)
				// thesis
			  ->orWhere('t.tutors LIKE ?', $value)
			  ->orWhere('t.department LIKE ?', $value)
			  ->orWhere('t.faculty LIKE ?', $value)
			  ->orWhere('t.knowledgeArea LIKE ?', $value)
			  // masterThesis
			  ->orWhere('mt.tutors LIKE ?', $value)
			  ->orWhere('mt.department LIKE ?', $value)
			  ->orWhere('mt.faculty LIKE ?', $value)
			  ->orWhere('mt.knowledgeArea LIKE ?', $value)
			  // phdThesis
			  ->orWhere('pt.tutors LIKE ?', $value)
			  ->orWhere('pt.department LIKE ?', $value)
			  ->orWhere('pt.faculty LIKE ?', $value)
			  ->orWhere('pt.knowledgeArea LIKE ?', $value)
			  // book
			  ->orWhere('b.city LIKE ?', $value)
			  ->orWhere('b.edition LIKE ?', $value)
			  ->orWhere('b.editors LIKE ?', $value)
			  ->orWhere('b.publisher LIKE ?', $value)
			  ->orWhere('b.knowledgeArea LIKE ?', $value)
			  // encyclopedia
			  ->orWhere('e.edition LIKE ?', $value)
			  ->orWhere('e.publisher LIKE ?', $value)
			  ->orWhere('e.publisher LIKE ?', $value)
			  // magazineArticle
			  ->orWhere('m.city LIKE ?', $value);
			  
		$result = $q->fetchArray();
		$total = $result[0]['total'];

		// return response to client
		echo json_encode(array('success' => true, 'message' => 'Datos cargardo exitosamente', 'documents' => $total, 'data' => $results));  
  }
}